#include "RealTimeWindow.hpp"
#include <stdexcept>
#include <spdlog/spdlog.h>

RealTimeWindow::RealTimeWindow(const std::string& projectname,const std::string & taskname)
{
  UIbuilder=Gtk::Builder::create();
  try
  {
    UIbuilder->add_from_file("RealtimeUI.ui");
  }
  catch(const Glib::FileError & ex)
  {
    spdlog::error("RealtimeUI FileError: {}",ex.what());
    throw;
  }
  catch(const Glib::MarkupError& ex)
  {
    spdlog::error("RealtimeUI MarkupError: {}",ex.what());
    throw;
  }
  catch(const Gtk::BuilderError& ex)
  {
    spdlog::error("RealtimeUI BuilderError: {}",ex.what());
    throw;
  }
  pWindow=UIbuilder->get_widget<Gtk::Window>("mainWindow");
  if(!pWindow)
    throw std::runtime_error("无法加载mainWindow对象");

  labInfo=UIbuilder->get_widget<Gtk::Label>("labInfo");
  if(!labInfo)
    throw std::runtime_error("无法加载labInfo对象");

  monitorAllList[0]=UIbuilder->get_widget<Gtk::DrawingArea>("drawCamera1");
  if(!monitorAllList[0])
    throw std::runtime_error("无法加载drawCamera1对象");
  monitorAllList[0]->set_draw_func(std::bind(&RealTimeWindow::on_draw,
    this,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,0));

  monitorAllList[1]=UIbuilder->get_widget<Gtk::DrawingArea>("drawCamera2");
  if(!monitorAllList[1])
    throw std::runtime_error("无法加载drawCamera2对象");
  monitorAllList[1]->set_draw_func(std::bind(&RealTimeWindow::on_draw,
    this,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,1));

  monitorAllList[2]=UIbuilder->get_widget<Gtk::DrawingArea>("drawCamera3");
  if(!monitorAllList[2])
    throw std::runtime_error("无法加载drawCamera3对象");
  monitorAllList[2]->set_draw_func(std::bind(&RealTimeWindow::on_draw,
    this,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,2));

  monitorAllList[3]=UIbuilder->get_widget<Gtk::DrawingArea>("drawCamera4");
  if(!monitorAllList[3])
    throw std::runtime_error("无法加载drawCamera4对象");
  monitorAllList[3]->set_draw_func(std::bind(&RealTimeWindow::on_draw,
    this,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,3));

  monitorAllList[4]=UIbuilder->get_widget<Gtk::DrawingArea>("drawCamera5");
  if(!monitorAllList[4])
    throw std::runtime_error("无法加载drawCamera5对象");
  monitorAllList[4]->set_draw_func(std::bind(&RealTimeWindow::on_draw,
    this,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,4));

  monitorSingle=UIbuilder->get_widget<Gtk::DrawingArea>("drawCameraSignal");
  if(!monitorSingle)
    throw std::runtime_error("无法加载drawCameraSignal对象");
  monitorSingle->set_draw_func(sigc::mem_fun(*this,&RealTimeWindow::on_draw_singleImage));

  btnShotControl=UIbuilder->get_widget<Gtk::Button>("btnShotControl");
  if(!btnShotControl)
    throw std::runtime_error("无法加载btnShotControl对象");
  btnShotControl->signal_clicked().connect(std::bind(&RealTimeWindow::on_btnShowControl_click,this));

  m_dispatcher.connect(sigc::mem_fun(*this,&RealTimeWindow::on_notification_from_work_thread));
  pWindow->signal_hide().connect(funcWindowsCloseCallback);
}

RealTimeWindow::~RealTimeWindow()
{
  delete pWindow;
}

void RealTimeWindow::test_call(Glib::RefPtr<Gtk::Application> app)
{
  app->add_window(*pWindow);
  pWindow->set_visible(true);
}

void RealTimeWindow::Show()
{
  pWindow->set_visible(true);
}

void RealTimeWindow::ShowOriginImage(const ImageType& data,int index)
{
  if(index>4) return;
  std::lock_guard<std::mutex> lck(originImageMutList[index]);
  originImageList[index]=Gdk::Pixbuf::create_from_data
    (data.data,Gdk::Colorspace::RGB,false,8,data.width,data.height,data.width*3,
     [](const guint8* data){delete [] data;});
  refreshOriginImageList[index]=true;
  m_dispatcher.emit();
}

void RealTimeWindow::ShowImageSingle(const ImageType& image)
{
  singleImage=Gdk::Pixbuf::create_from_data
    (image.data,Gdk::Colorspace::RGB,false,8,image.width,image.height,image.width*3,
    [](const guint8* data){delete [] data;});
  refreshFlag=true;
  m_dispatcher.emit();
}

void RealTimeWindow::on_startShot_click(const sigc::slot<void(Gtk::Button*)>& slot)
{
  btnShotControl->signal_clicked().connect(sigc::bind(slot,btnShotControl));
}

void RealTimeWindow::on_notification_from_work_thread()
{
  for(int i=0;i<5;i++)
  { if(refreshOriginImageList[i])
    {
      monitorAllList[i]->queue_draw();
      refreshOriginImageList[i]=false;
    }
  }
  if(refreshFlag)
  {
    monitorSingle->queue_draw();
    refreshFlag=false;
  }
}

void RealTimeWindow::on_draw(const Cairo::RefPtr<Cairo::Context>& cr,int width,int height,int index)
{
  if(!originImageList[index])
  {
    cr->set_source_rgb(1,1,1);
    cr->rectangle(0,0,width,height);
    cr->fill();
    cr->paint();
  }
  else
  {
    Gtk::DrawingArea* ptr=monitorAllList[index];
    Gdk::Cairo::set_source_pixbuf(cr, 
      originImageList[index]->scale_simple(
        ptr->get_width(),
        ptr->get_width()*originImageList[index]->get_height()/originImageList[index]->get_width(),
        Gdk::InterpType::NEAREST),
      0, 
      0);
    cr->paint();
  }
}

void RealTimeWindow::on_draw_singleImage(const Cairo::RefPtr<Cairo::Context>& cr, int width,int height)
{
  if(!singleImage)
  {
    cr->set_source_rgb(1,1,1);
    cr->rectangle(0,0,width,height);
    cr->fill();
    cr->paint();
  }
  else
  {
    Gtk::DrawingArea* ptr=monitorSingle;
    Gdk::Cairo::set_source_pixbuf(cr, 
      singleImage->scale_simple(
        ptr->get_width(),
        ptr->get_width()*singleImage->get_height()/singleImage->get_width(),
        Gdk::InterpType::NEAREST),
      0, 
      0);
    cr->paint();
  }

}

void RealTimeWindow::on_btnShowControl_click()
{
  funcRecordCallback(onShotControl);
  if(onShotControl) btnShotControl->set_label("停止拍摄");
  else btnShotControl->set_label("开始拍摄");
  onShotControl=!onShotControl;
}
